/*
 * Copyright © 2009 Gerald Isaac Schwarz
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package driver;

import java.awt.Dimension;
import java.awt.Point;
import java.util.ArrayList;

public interface Driver {
	public Piece getPiece(Point location);
	
	public boolean isEmpty(Point location);
	
	public base.Engine getEngine();
	
	public ArrayList<String> getTypes();
	
	/**
	 * Get all the currently applicable upgrades to the piece in the specified location.
	 * @param location
	 * @return An ArrayList of all the upgrades that can be applied.
	 */
	public ArrayList<String> getUpgrades(Point location);
	
	/**
	 * Get the dimentions of the board.
	 * @return The dimentions of the board.
	 */
	public Dimension getBoardSize();
	
	/**
	 * Get the maximum number of players the interface layer may provide for the game.
	 * @return The maximum number of players the interface layer may provide for the game.
	 */
	public int getMaximumNumberOfPlayers();
	
	/**
	 * Get the minimum number of players the interface layer must provide for the game.
	 * @return The minimum number of players the interface layer must provide for the game.
	 */
	public int getMinimumNumberOfPlayers();
	
	/**
	 * Set the players that will be participating in the game.
	 * @param players The players that will be participating in the game.
	 * @throws TooFewPlayersException If the list of players is too short.
	 * @throws TooManyPlayersException If the list of players is too long.
	 */
	public void setPlayers(ArrayList<Player> players) throws TooFewPlayersException, TooManyPlayersException;
	
	/**
	 * Set the player that will be participating in the game.
	 * @param player The player that will be participating in the game.
	 */
	public void setPlayer(Player player) throws TooFewPlayersException, TooManyPlayersException;
	
	/**
	 * Get all the players in the game.
	 * @return An ArrayList of all the players in the game.
	 */
	public ArrayList<Player> getPlayers();
	
	/**
	 * Get the player who's currently moving.
	 * @return The player who's currently moving.
	 */
	public int getCurrentPlayerIndex();
	
	/**
	 * Get the player who's currently moving.
	 * @return The player who's currently moving.
	 */
	public Player getCurrentPlayer();
	
	/**
	 * Get the player that's associated with the specified index number.
	 * @param index The index number that identifies the player.
	 * @return The player that's associated with the specified index number.
	 */
	public Player getPlayerByIndex(int index);
	
	/**
	 * Get the index number of the specified player.
	 * @param player The player who's index number will be retrieved.
	 * @return The index number of the specified player.
	 */
	public int getPlayerIndex(Player player);
	
	/**
	 * Get all the pieces currently on the board.
	 * @return An ArrayList of all the pieces that are currently on the board. 
	 */
	public ArrayList<Piece> getPieces();
	
	/**
	 * Get all the pieces being held captive by the specified player.
	 * @param player The player which is being examined.
	 * @return An ArrayList of all the pieces being held captive by the specified player.
	 */
	public ArrayList<Piece> getCapturedPieces(int index);
	
	/**
	 * Check whether or not the specified player is in check.
	 * @param player The player which is being examined.
	 * @return True if the player is in check, false if he's not.
	 */
	public boolean isInCheck(int index);
	
	/**
	 * Check whether or not the specified player is in checkmate.
	 * @param player The player which is being examined.
	 * @return True if the player is in checkmate, false if he's not.
	 */
	public boolean isInCheckmate(int index);
	
	/**
	 * Use this to end the turn and pass control to the next player in the game.
	 */
	public void endTurn() throws TurnNotFinishedException;
	
	/**
	 * Check whether or not the turn can be ended without upgrading the specified piece.
	 * @param piece The piece which is being examined.
	 * @return True if the piece must be upgraded, false if the turn can end without upgrading it.
	 */
	public boolean mustBeUpgraded(Point location);
	
	/**
	 * Check whether or not the piece can be upgraded.
	 * @param piece The piece which is being examined.
	 * @return True if the piece can be upgraded, false if it can't. 
	 */
	public boolean canBeUpgraded(Point location);
	
	public void addTurnListener(TurnListener turnListener);
	public void removeTurnListener(TurnListener turnListener);
	
	/**
	 * Check whether or not the game supports moving pieces.
	 * @return True if it does, false if it doesn't.
	 */
	public boolean supportsMove();
	
	/**
	 * Check whether or not the game supports dropping pieces.
	 * @return True if it does, false if it doesn't.
	 */
	public boolean supportsDrop();
	
	/**
	 * Check whether or not the game supports castling.
	 * @return True if it does, false if it doesn't.
	 */
	public boolean supportsCastle();
	
	/**
	 * Check whether or not the game supports upgrading pieces.
	 * @return True if it does, false if it doesn't.
	 */
	public boolean supportsUpgrade();
	
	/**
	 * Check whether or not the proposed move is legal.
	 * @param piece The piece to be moved.
	 * @param destination The proposed destination.
	 * @return True if it is, false if it isn't.
	 * @throws MoveNotSupportedException If moving isn't supported by the game.
	 */
	public boolean isValidMove(Point location, Point destination) throws MoveNotSupportedException;
	
	/**
	 * Check whether or not the proposed drop is legal.
	 * @param piece The piece to be dropped.
	 * @param destination The proposed destination.
	 * @return True if it is, false if it isn't.
	 * @throws DropNotSupportedException If dropping isn't supported by the game.
	 */
	public boolean isValidDrop(int index, Point destination) throws DropNotSupportedException;
	
	/**
	 * Check whether or not the proposed castling is legal.
	 * @param piece The rook with which the castling will be performed.
	 * @return True if it is, false if it isn't.
	 * @throws CastleNotSupportedException If castling isn't supported by the game.
	 */
	public boolean isValidCastle(Point location) throws CastleNotSupportedException;
	
	/**
	 * Check whether or not the proposed upgrade is legal.
	 * @param piece The piece to be upgraded.
	 * @param type The proposed upgrade.
	 * @return True if it is, false if it isn't.
	 * @throws UpgradeNotSupportedException If upgrading isn't supported by the game.
	 */
	public boolean isValidUpgrade(Point location, String type) throws UpgradeNotSupportedException;
	
	/**
	 * Perform the specified move.
	 * @param piece The piece to be moved.
	 * @param destination The proposed destination.
	 * @throws MoveNotSupportedException If moving isn't supported by the game.
	 * @throws InvalidMoveException If the move isn't legal.
	 */
	public void move(Point location, Point destination) throws MoveNotSupportedException, InvalidMoveException;
	
	/**
	 * Perform the specified drop.
	 * @param piece The piece to be dropped.
	 * @param destination The proposed destination.
	 * @throws DropNotSupportedException If dropping isn't supported by the game.
	 * @throws InvalidDropException If the drop isn't legal.
	 */
	public void drop(int index, Point destination) throws DropNotSupportedException, InvalidDropException;
	
	/**
	 * Perform the specified castling.
	 * @param piece The rook with which the castling will be performed.
	 * @throws CastleNotSupportedException If castling isn't supported by the game.
	 * @throws InvalidCastleException If the drop isn't legal.
	 */
	public void castle(Point location) throws CastleNotSupportedException, InvalidCastleException;
	
	/**
	 * Perform the specified upgrade.
	 * @param piece The piece to be upgraded.
	 * @param type The proposed upgrade.
	 * @throws UpgradeNotSupportedException If upgrading isn't supported by the game.
	 * @throws InvalidUpgradeException If the upgrade isn't legal.
	 */
	public void upgrade(Point location, String type) throws UpgradeNotSupportedException, InvalidUpgradeException;
}